package com.example.service;

import com.example.util.MDCUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

@Service
@Slf4j
public class FutureExampleService {

    private final ExecutorService executorService = Executors.newFixedThreadPool(3);

    // 提交并执行单个任务
    public Future<String> executeTask() {
        Callable<String> task = MDCUtil.wrapWithMdc(() -> {
            log.info("线程 {} 开始执行任务", Thread.currentThread().getName());
            Thread.sleep(2000);
            log.info("线程 {} 任务完成", Thread.currentThread().getName());
            return "任务完成";
        });

        log.info("提交任务到线程池");
        Future<String> future = executorService.submit(task);
        log.info("任务提交成功");
        return future;
    }

    // 提交并取消任务
    public void cancelTask() throws InterruptedException {
        Future<String> future = executeTask();
        Thread.sleep(1000);  // 模拟一些延迟
        boolean canceled = future.cancel(true);  // 试图取消任务
        log.info("任务是否取消: {}", canceled);
    }

    // 检查任务是否完成
    public void checkIfTaskIsDone() throws InterruptedException {
        Future<String> future = executeTask();
        while (!future.isDone()) {
            log.info("任务仍在进行中...");
            Thread.sleep(500);
        }
        try {
            String result = future.get();  // 阻塞直到任务完成
            log.info("任务完成，结果为: {}", result);
        } catch (ExecutionException | InterruptedException e) {
            log.error("获取任务结果时出错", e);
        }
    }

    // 使用 invokeAll 同时提交多个任务
    public void executeMultipleTasks() throws InterruptedException {
        List<Callable<String>> tasks = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            int taskId = i;
            tasks.add(MDCUtil.wrapWithMdc(() -> {
                log.info("任务 {} 开始执行", taskId);
                Thread.sleep(2000);
                return "任务 " + taskId + " 完成";
            }));
        }

        List<Future<String>> futures = executorService.invokeAll(tasks);

        for (Future<String> future : futures) {
            try {
                log.info("任务结果: {}", future.get());  // 阻塞直到任务完成
            } catch (ExecutionException | InterruptedException e) {
                log.error("获取任务结果时出错", e);
            }
        }
    }

    // 使用 invokeAny 提交多个任务，获取第一个完成的任务结果
    public void executeAnyTask() {
        List<Callable<String>> tasks = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            int taskId = i;
            tasks.add(MDCUtil.wrapWithMdc(() -> {
                log.info("任务 {} 开始执行", taskId);
                Thread.sleep(2000 + taskId * 100);  // 模拟不同的执行时间
                return "任务 " + taskId + " 完成";
            }));
        }

        try {
            String result = executorService.invokeAny(tasks);
            log.info("第一个完成的任务结果为: {}", result);
        } catch (ExecutionException | InterruptedException e) {
            log.error("执行任务时出错", e);
        }
    }

    // 关闭线程池
    public void shutdownExecutor() {
        log.info("关闭线程池");
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                log.warn("线程池未在5秒内终止，强制关闭...");
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            log.error("线程池关闭时被中断", e);
            executorService.shutdownNow();
        }
    }
}
